#ifndef VENDOR_ECARX_TCAM_V1_0_TCAM_H
#define VENDOR_ECARX_TCAM_V1_0_TCAM_H

#include <WorkerThread.h>
#include <android/hardware/automotive/vehicle/2.0/IVehicle.h>
#include <ipcp/ipcp.h>
#include <log/log.h>
#include <unistd.h>
#include <vendor/ecarx/xma/automotive/vehicle/2.0/types.h>
//#include <vendor/ecarx/xma/dtcnl/1.0/IDtcnl.h>
#include <vendor/ecarx/xma/iplm/1.0/IIplm.h>
#include <vendor/ecarx/xma/tcam/1.0/ITcam.h>
#include <vendor/ecarx/xma/tcam/1.0/ITcamCallback.h>
#include <vendor/ecarx/xma/tcam/1.0/types.h>

#include "Utils.h"
namespace vendor {
namespace ecarx {
namespace xma {
namespace tcam {
namespace V1_0 {

using std::lock_guard;
using std::mutex;
using std::chrono::milliseconds;
using std::chrono_literals::operator""ms;
using ::android::sp;
using ::android::wp;
using ::android::hardware::hidl_death_recipient;
using ::android::hardware::hidl_string;
using ::android::hardware::hidl_vec;
using ::android::hardware::Return;
using ::android::hardware::Void;
using std::string;
// using ::vendor::ecarx::xma::dtcnl::V1_0::IDtcnl;
using ::vendor::ecarx::xma::iplm::V1_0::IIplm;
using ::vendor::ecarx::xma::iplm::V1_0::IPLM_Preconfigured_Service;
using ::vendor::ecarx::xma::iplm::V1_0::IPLM_ResourceGroup_Index;
using ::vendor::ecarx::xma::iplm::V1_0::IPLM_RG_PRIO;
using ::vendor::ecarx::xma::iplm::V1_0::IPLM_RG_State;
using ::vendor::ecarx::xma::iplm::V1_0::ServiceStatus;
using ::vendor::ecarx::xma::tcam::V1_0::CallType;
using ::vendor::ecarx::xma::tcam::V1_0::Collectfunction;
using ::vendor::ecarx::xma::tcam::V1_0::Datacollection;
using ::vendor::ecarx::xma::tcam::V1_0::ETAInfo;
using ::vendor::ecarx::xma::tcam::V1_0::GenericStatus;
using ::vendor::ecarx::xma::tcam::V1_0::HangupCall;
using ::vendor::ecarx::xma::tcam::V1_0::IHUStatusCommand;
using ::vendor::ecarx::xma::tcam::V1_0::IpAddress;
using ::vendor::ecarx::xma::tcam::V1_0::LanguageType;
using ::vendor::ecarx::xma::tcam::V1_0::LightShowMode;
using ::vendor::ecarx::xma::tcam::V1_0::LocalBookChrgnInfo;
using ::vendor::ecarx::xma::tcam::V1_0::PrivateLockCtrlResp;
using ::vendor::ecarx::xma::tcam::V1_0::PrivateLockPasswordResp;
using ::vendor::ecarx::xma::tcam::V1_0::Remotediagnostics;
using ::vendor::ecarx::xma::tcam::V1_0::SettingParamsRequest;
using namespace ::android::hardware::automotive::vehicle::V2_0;
using ::vendor::ecarx::xma::automotive::vehicle::V2_0::DirectTransmitProperty;
using ::vendor::ecarx::xma::tcam::V1_0::BookTravelGet;
using ::vendor::ecarx::xma::tcam::V1_0::BookTravelGetResponse;
using ::vendor::ecarx::xma::tcam::V1_0::ProFileID;
using ::vendor::ecarx::xma::tcam::V1_0::RemoteChatVideoComResp;
using ::vendor::ecarx::xma::tcam::V1_0::SecRowFaceInfoUploadSts;

#define ASN_HEADER_LENGTH_OFFSET 8

#define LOCAL_IP "198.18.34.15"
#define PEER_IP "198.18.32.17"
#define PEER_DMM_IP "198.18.32.18"

// service id
#define SERVICE_ID_ELECTRICALPOWER 0xa4
#define SERVICE_ID_SEC_ROW_FACIAL_RECOGNITION 0xa6
#define SERVICE_ID_XCALL 0xa9
#define SERVICE_ID_RVDC 0xac
#define SERVICE_ID_VEHICLE_VIDEO_BY_CHAT_CAMERA 0xb7
#define SERVICE_ID_PRIVATELOCKING 0xb9
#define SERVICE_ID_LIGHT_SHOW 0xba
#define SERVICE_ID_GID_PROF 0xbd
#define SERVICE_ID_BOOK_TRAVEL 0xbe


// service port
#define PORT_ELECTRICALPOWER 50164
#define PORT_SEC_ROW_FACIAL_RECOGNITION 50166
#define PORT_XCALL 50169
#define PORT_RVDC 50172
#define PORT_VEHICLE_VIDEO_BY_CHAT_CAMERA 50183
#define PORT_PRIVATE_LOCKING 50185
#define PORT_LIGHT_SHOW 50186
#define PORT_GID_PROF 50189
#define PORT_BOOK_TRAVEL 50190

// op type
#define OP_TYPE_REQUEST 0x00
#define OP_TYPE_SET_REQUEST_NO_RETURN 0x01
#define OP_TYPE_SET_REQUEST 0x02
#define OP_TYPE_RESPONSE 0x04
#define OP_TYPE_NOTIFICATION 0x05
#define OP_TYPE_NOTIFICATION_CYC 0x06
#define OP_TYPE_ERROR 0xe0

// 7.1.1.2 TransferElectricalPower(0xA4)
#define OP_ID_ELECTRICALPOWER_LOCALBOOKCHRGN 0x0001
#define OP_ID_ELECTRICALPOWER_REMOTEBOOKCHRGN 0x000d
#define OP_ID_ELECTRICALPOWER_REQUESTCHRGN 0x001B
#define OP_ID_ELECTRICALPOWER_BOOK_CHRGN_RESP 0x0010
#define OP_ID_ELECTRICALPOWER_LOCAL_RESERVATION_CHRGN_SET 0x001C
#define OP_ID_ELECTRICALPOWER_RESERVATION_CHARGN_SETG_GET 0x001D
#define OP_ID_ELECTRICALPOWER_REMOTE_RESERVATION_CHRGN_SETG_SYNCN 0x0020
#define OP_ID_ELECTRICALPOWER_SINGLE_RESERVATION_CHRGN_END 0x0021
#define OP_ID_ELECTRICALPOWER_RESERVATION_CHRGN_SET 0x0022
#define OP_ID_ELECTRICALPOWER_REMOTE_RESERVATION_CHRGN_SETG_GET 0x0023
#define OP_ID_ELECTRICALPOWER_REMOTE_RESERVATION_CHRGN_SET_SYN 0x0024
#define OP_ID_ELECTRICALPOWER_RESERVATION_CHARGN_STS_CHANGE_BY_CONFLICT 0x0025
#define OP_ID_ELECTRICALPOWER_BOOKTRVLSTS_CHANGE_BY_CONFLICT 0x0026

// 7.1.1.3 XCALL (0xA9)
#define OP_ID_XCALL_XCALL_STATUS 0x0001
#define OP_ID_XCALL_IHUSTATUS_REPORT 0x0002
#define OP_ID_XCALL_XCALL_CONTROL 0x0003
#define OP_ID_XCALL_MUTE_COMMAND 0x0004
#define OP_ID_XCALL_CALL_CENTER_PRE 0x0005
#define OP_ID_XCALL_POIINFO_PUSH 0x0006
#define OP_ID_XCALL_CALLBACKSTS 0x0007
#define OP_ID_XCALL_ETAINFO 0x0008
#define OP_ID_XCALL_PREMIUM_AUDIO 0x0009

// 7.1.1.5 RVDC (0xAC)
#define OP_ID_RVDC_LANGSETTINGS 0x0c53
#define OP_ID_RVDC_AUTHORIZATION_STATUS_REQUEST 0x0C02
#define OP_ID_RVDC_AUTHORIZATION_STATUS_NOTIFICATION 0x0C03
#define OP_ID_RVDC_AUTHORIZATION_STATUS_USER_UPDATE 0x0C04

// 7.1.1.9 VehicleVideoByChatCamera (0xB7)
#define OP_ID_PLAY_CHAT_VIDEO_LIVEVIEW 0x0002
#define OP_ID_STOP_CHAT_VIDEO_LIVEVIEW 0x0003
#define OP_ID_REMOTE_CHAT_VIDEO_TIMEOUT 0x0004
#define OP_ID_REMOTE_CHAT_VIDEO_TIOUT_NOTIF 0x0005

// 7.1.1.9 PrivateLockingInterStorage (0xB9)
#define OP_ID_PRIVATELOCKING_CNTR 0x0001
#define OP_ID_PRIVATELOCKING_PWD 0x0002

// 7.1.1.10 ExteriorLightShow (0xBA)
#define OP_ID_REQUEST_EXTERNAL_TCAM_IP 0x0001
#define OP_ID_SLAVE_TCAM_EX_IP 0x0002
#define OP_ID_MASTER_TCAM_EX_IP 0x0003
#define OP_ID_LIGHT_SHOW_MODE 0x0004

// 7.1.1.12.2 GIDProfIDLnk (0xBD)
#define OP_ID_GIDPROFIDLNK 0x0001

// 7.1.1.13 BookTravel (0xBE)
#define OP_ID_BOOK_TRAVEL_GET 0x0001
#define OP_ID_BOOK_TRAVEL_SET 0x0002
#define OP_ID_REMOTE_BOOK_TRAVEL_GET 0x0003
#define OP_ID_CHARG_START_TIME_SYNC 0x0004

// 7.1.1.14 SecRowFacialRecognition (0xA6)
#define OP_ID_SEC_ROW_FACE_REGISTER 0x0001
#define OP_ID_SEC_ROW_FACE_SGN_IN_PICTURE_CENTER 0x0002
#define OP_ID_SEC_ROW_FACE_SGN_IN_PICTURE_RE 0x0003
#define OP_ID_SEC_ROW_FACE_RECOGNITION_REQ 0x0004
#define OP_ID_SEC_ROW_FACE_INFO_CNCL_GID 0X0005
#define OP_ID_SEC_ROW_FACE_INFO_UPLOAD_FB 0x0007

// Charging time
#define TIME_DEFAULT 0
#define START_TIME "persist.sys.charging.start.time"
#define STOP_TIME "persist.sys.charging.stop.time"
#define SWITCH_STATUS "persist.sys.charging.switch.status"

class Tcam : public ITcam {
   public:
    Tcam();

    ~Tcam();

    virtual void onFirstRef();

    int init_vehicle_server();
    void setupIPLM();
    void setupIPCP();
    void setupDtcnl();
    void reportDtc();

    Return<StatusCode> requestXCallStatus() override;

    Return<StatusCode> requestCallbackRemainTime() override;

    Return<StatusCode> requestETAInfo() override;

    Return<StatusCode> subscribe(const ::android::sp<ITcamCallback>& callback) override;

    Return<StatusCode> unsubscribe(const ::android::sp<ITcamCallback>& callback) override;

    Return<StatusCode> notifyLocalChrgnInfo(const LocalBookChrgnInfo& localBookChrgnInfo) override;

    Return<StatusCode> notifyLanguageStatus(LanguageType LanguageType) override;

    Return<StatusCode> notifyIHUStatusReport(IHUStatusCommand status) override;

    Return<StatusCode> notifyXCallControl(HangupCall hangupCall, CallType callType) override;

    Return<StatusCode> notifyCallcenterPre(CallCenterPreference callCenterPreference) override;

    Return<StatusCode> notifyPremiumAudioStatus(GenericStatus micStatus,
                                                GenericStatus speakerStatus) override;
    Return<StatusCode> responsePremiumAudioStatus(GenericStatus micStatus,
                                                  GenericStatus speakerStatus) override;
    Return<StatusCode> responsePrivateLockPassword(
        PrivateLockPasswordResp privateLockPasswordResp) override;

    Return<StatusCode> responsePrivateLockCtrlResp(
        PrivateLockCtrlResp privateLockCtrlResp) override;

    Return<StatusCode> requestRVDCAuthorizationStatus() override;

    Return<StatusCode> setRequestRVDCAuthorizationStatusUserUpdate(
        Collectfunction collectFunction, Datacollection dataCollection,
        Remotediagnostics remoteDiagnostics) override;

    Return<StatusCode> requestExternalTcamIp() override;

    Return<StatusCode> notifyLightShowModeCyclic(LightShowMode lightShowMode) override;

    Return<StatusCode> requestChargeInfo(SettingParamsRequest settingParamsRequest) override;
    Return<StatusCode> requestBookChargeInfo_Use0x23(BookChargingGet bookChargingGet) override;
    Return<StatusCode> requestBookChargeInfo_Use0x1D(BookChargingGet bookChargingGet) override;
    Return<StatusCode> setBookCharging_Use0x22(const BookChargingGetResponse& bookChargingGetResponse) override;
    Return<StatusCode> setBookCharging_Use0x1C(const BookChargingGetResponse& bookChargingGetResponse) override;
    Return<StatusCode> notifyGIDProfIDLnk(const hidl_string& gid, ProFileID profId) override;

    Return<StatusCode> setBookTravel(const BookTravelGetResponse& setBookTravelInfo) override;

    Return<StatusCode> requestBookTravel(BookTravelGet bookTravelGet) override;

    Return<StatusCode> responsePlayChatVideoLiveview(
        RemoteChatVideoComResp remoteChatVideoComResp) override;

    Return<StatusCode> responseStopChatVideoLiveview(
        RemoteChatVideoComResp remoteChatVideoComResp) override;

    Return<StatusCode> notifyRemoteChatVideoTimeOut() override;
    Return<StatusCode> notifyRemoteChatVideoTiOutNotif() override;

    Return<StatusCode> requestSecRowFaceRecognitionReq(SecRowFaceInfoReq secRowFaceInfoReq, const hidl_string& secRowFaceInfoReqGID) override;
    Return<StatusCode> notifySecRowFaceRegister(const hidl_string& secRowFaceInfoAcqGid, const hidl_string& secRowfaceInfoAcqImg) override;
    Return<StatusCode> requestSecRowFaceSgnInPictureRe(const hidl_string& secondRowfaceInfosynImg) override;
    Return<StatusCode> notifySecRowFaceInfoCnclGid(const hidl_string& secRowFaceInfoCnclGid) override;
    Return<StatusCode> responseSecRowFaceSgnInPictureCenter(FirstRowfaceInfosynSts firstRowfaceInfosynSts) override;

    sp<ITcamCallback> getCallback();
    static sp<Tcam> getTcam();
    void setTimeProperty(DateTime startTime, DateTime stopTime, int switchStatus);
    bool getChargingStatus(RemoteBookChrgnInfo& info);

    void handleHidlDeath();
    void handleTcamServiceCallbackDeath();
    void handleVehicleHidlDeath();
    void setResourceGroupWithPriority(IPLM_ResourceGroup_Index resourceGroup,
                                      IPLM_RG_PRIO priority);
    void setRvdcResourceGroup();
    void setGIDProfIDLnkResourceGroup();
    void setBookTravelResourceGroup();
    void setECallResourceGroup();
    void setChargingResourceGroup();
    void setPrivateLockResourceGroup();
    void setVehicleVideoResourceGroup();
    void setSecRowFacialRecognitionResourceGroup();
    std::thread mIpcpThread;

   private:
    class DeathRecipient : public hidl_death_recipient {
       public:
        DeathRecipient(sp<Tcam> tcam) : mTcam(tcam) {}
        ~DeathRecipient() = default;
        virtual void serviceDied(uint64_t cookie /*cookie*/,
                                 const wp<::android::hidl::base::V1_0::IBase>& /*who*/) {
            ALOGD("function: %s, service %lu", __func__, cookie);
            mTcam->handleHidlDeath();
        }

       private:
        sp<Tcam> mTcam;
    };

   private:
    class TcamServiceCallBackDeathRecipient : public hidl_death_recipient {
       public:
        TcamServiceCallBackDeathRecipient(sp<Tcam> tcam) : mTcam(tcam) {}
        ~TcamServiceCallBackDeathRecipient() = default;
        virtual void serviceDied(uint64_t cookie /*cookie*/,
                                 const wp<::android::hidl::base::V1_0::IBase>& /*who*/) {
            ALOGD("function: %s, service %lu", __func__, cookie);
            mTcam->handleTcamServiceCallbackDeath();
        }

       private:
        sp<Tcam> mTcam;
    };

   private:
    class VehicleDeathRecipient : public hidl_death_recipient {
       public:
        VehicleDeathRecipient(sp<Tcam> tcam) : mTcam(tcam) {}
        ~VehicleDeathRecipient() = default;
        virtual void serviceDied(uint64_t cookie /*cookie*/,
                                 const wp<::android::hidl::base::V1_0::IBase>& /*who*/) {
            ALOGD("function: %s, service %lu", __func__, cookie);
            mTcam->handleVehicleHidlDeath();
        }

       private:
        sp<Tcam> mTcam;
    };

   private:
    mutex mMut;
    sp<ITcamCallback> mCallback;
    WorkerThread mThread;
    sp<IIplm> mIPLM;
    sp<DeathRecipient> mIplmCallbackDeathRecipient;
    sp<TcamServiceCallBackDeathRecipient> mTcamServiceCallbackDeathRecipient;
    sp<VehicleDeathRecipient> mVehicleDeathRecipient;
    // sp<IDtcnl> mDtcnl;
    static Tcam* sTcam;
};

}  // namespace V1_0
}  // namespace tcam
}  // namespace xma
}  // namespace ecarx
}  // namespace vendor
#endif  // VENDOR_ECARX_TCAM_V1_0_TCAM_H
